{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://pptwinpics.oss-cn-beijing.aliyuncs.com/CDA%E8%AE%B2%E5%B8%88%E6%B0%B4%E5%8D%B0_20200314161940.png)\n",
    "\n",
    "大家好，我是 CDA 曹鑫。\n",
    "\n",
    "我的 Github 地址：https://github.com/imcda 。\n",
    "\n",
    "我的邮箱：caoxin@cda.cn 。\n",
    "\n",
    "这节课跟大家讲讲 Numpy。\n",
    "\n",
    "# Numpy 介绍\n",
    "Numpy 是 Python 语言科学计算的核心库；Numpy 主要提供高性能的多维对象数组\n",
    "(array),以及用于计算array的工具。\n",
    "\n",
    "## 主要特性:\n",
    "- a powerful N-dimensional array object (高性能N维array object)\n",
    "- sophisticated (broadcasting) functions (广播函数)\n",
    "- tools for integrating C/C++ and Fortran code (多语言接口工具)\n",
    "- useful linear algebra, Fourier transform, and random number capabilities (线代，傅里叶变换，随机数等数学功能)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入numpy的方式:\n",
    "import numpy as np # 用得最多 \n",
    "# from numpy import *\n",
    "# import numpy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Array:数组\n",
    "\n",
    "**数据类型：ndarray**\n",
    "\n",
    "一个numpy数组是一个由不同数值组成的网格。网格中的数据都是同一种数据类型，可以通过非负整型数的元组来访问。维度的数量被称为数组的阶，数组的大小是一个由整型数构成的元组，可以描述数组不同维度上的大小。\n",
    "\n",
    "- Numpy的数组，是一个值格\n",
    "- 包含的元素有相同的类型\n",
    "- 由一个非负数组成元素的元组来索引数组中的元素(当然可以由负数索引)\n",
    "- 数组的秩(rank):数组维度的个数\n",
    "- 数组的形状(shape):由元组中的整数元素来表示数组每一个维度的长度(size)\n",
    "\n",
    "我们可以从列表创建数组，然后利用方括号访问其中的元素：\n",
    "\n",
    "# 创建数组(Array Creation)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个一维数组\n",
    "a = np.array([1, 2, 3])\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "1\n",
      "(3,)\n",
      "1 2 3\n"
     ]
    }
   ],
   "source": [
    "print(type(a)) # 类型\n",
    "print(a.ndim)  # 秩,用.ndim查看。\n",
    "print(a.shape) # \n",
    "print(a[0], a[1], a[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5 2 3]\n"
     ]
    }
   ],
   "source": [
    "# 修改数组中的一个元素\n",
    "a[0]=5 \n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个二维数组\n",
    "b = np.array([[1, 2, 3],\n",
    "              [4, 5, 6]])\n",
    "print(b)\n",
    "\n",
    "# 其他方法创建一个二维数组\n",
    "# b = np.array(([1,2,3],[4,5,6])) \n",
    "# b = np.array(((1,2,3),(4,5,6)))\n",
    "# print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "2\n",
      "(2, 3)\n",
      "1 2 4\n"
     ]
    }
   ],
   "source": [
    "print(type(b)) # 类型\n",
    "print(b.ndim) \n",
    "print(b.shape)\n",
    "print(b[0, 0], b[0, 1], b[1, 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1 10  3]\n",
      " [ 4  5  6]]\n"
     ]
    }
   ],
   "source": [
    "# 修改数组中的一个元素\n",
    "b[0,1]=10 \n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 思考题：创建一个三维数组\n",
    "对多维数组进一步理解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个三维数组？\n",
    "c = np.array([[1, 2, 3],\n",
    "              [4, 5, 6],\n",
    "              [7, 8, 9]])\n",
    "print(c)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "(3, 3)\n"
     ]
    }
   ],
   "source": [
    "print(c.ndim) \n",
    "print(c.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 2 3]\n",
      "  [4 5 6]\n",
      "  [7 8 9]]]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个三维数组！\n",
    "d = np.array([[[1, 2, 3],\n",
    "              [4, 5, 6],\n",
    "              [7, 8, 9]]])\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "(1, 3, 3)\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "print(d.ndim) \n",
    "print(d.shape)\n",
    "print(d.size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 2]\n",
      "  [3 4]\n",
      "  [5 6]]\n",
      "\n",
      " [[1 2]\n",
      "  [3 4]\n",
      "  [5 6]]]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个三维数组的方法\n",
    "c= np.array([[[1,2],\n",
    "              [3,4],\n",
    "              [5,6]],\n",
    "             \n",
    "             [[1,2],\n",
    "              [3,4],\n",
    "              [5,6]]])\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "(2, 3, 2)\n",
      "12\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "print(c.ndim) \n",
    "print(c.shape)\n",
    "print(c.size)\n",
    "print(c[0,1,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建数组的多种方式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Numpy还提供了很多其他创建数组的方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0.]\n",
      " [0. 0.]]\n",
      "\n",
      "\n",
      "[[1. 1.]]\n",
      "\n",
      "\n",
      "[[8 8]\n",
      " [8 8]]\n",
      "\n",
      "\n",
      "[[1. 0. 0. 0.]\n",
      " [0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]\n",
      " [0. 0. 0. 1.]]\n",
      "\n",
      "\n",
      "[[0.07605873 0.83892443 0.9785524 ]\n",
      " [0.902584   0.24165667 0.36570738]]\n"
     ]
    }
   ],
   "source": [
    "a = np.zeros((2,2))  # Create an array of all zeros\n",
    "print(a)              # Prints \"[[ 0.  0.]\n",
    "print(\"\\n\")             #          [ 0.  0.]]\"\n",
    "\n",
    "b = np.ones((1,2))   # Create an array of all ones\n",
    "print(b)              # Prints \"[[ 1.  1.]]\"\n",
    "print(\"\\n\")\n",
    "\n",
    "c = np.full((2,2), 8) # Create a constant array\n",
    "print(c)               # Prints \"[[ 7.  7.]\n",
    "print(\"\\n\")              #          [ 7.  7.]]\"\n",
    "\n",
    "d = np.eye(4)        # Create a 2x2 identity matrix（对角矩阵）\n",
    "print(d)              # Prints \"[[ 1.  0.]\n",
    "print(\"\\n\")             #          [ 0.  1.]]\"\n",
    "    \n",
    "# 这里就应该又怒疑问，这是什么？要学会搜索：https://blog.csdn.net/m0_37393514/article/details/81455915\n",
    "# 使用 shift+tab 可以查看用法\n",
    "\n",
    "e = np.random.random((2,3)) # Create an array filled with random values\n",
    "print(e)                     # Might print \"[[ 0.91940167  0.08143941]\n",
    "                            #               [ 0.68744134  0.87236687]]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一、np.eye()\n",
    "函数的原型：`numpy.eye(N,M=None,k=0,dtype=<class 'float'>,order='C)`\n",
    "\n",
    "返回的是一个二维2的数组(N,M)，对角线的地方为1，其余的地方为0.\n",
    "\n",
    "### 参数介绍：\n",
    "\n",
    "（1）N:int型，表示的是输出的行数\n",
    "\n",
    "（2）M：int型，可选项，输出的列数，如果没有就默认为N\n",
    "\n",
    "（3）k：int型，可选项，对角线的下标，默认为0表示的是主对角线，负数表示的是低对角，正数表示的是高对角。\n",
    "\n",
    "（4）dtype：数据的类型，可选项，返回的数据的数据类型\n",
    "\n",
    "（5）order：{‘C’，‘F'}，可选项，也就是输出的数组的形式是按照C语言的行优先’C'，还是按照Fortran形式的列优先‘F'存储在内存中\n",
    "\n",
    "### 案例：（普通的用法）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 0. 0.]\n",
      " [0. 1. 0.]\n",
      " [0. 0. 1.]]\n",
      "\n",
      "\n",
      "[[0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]\n",
      " [0. 0. 0. 1.]\n",
      " [0. 0. 0. 0.]]\n",
      "\n",
      "\n",
      "[[0. 0. 0. 0.]\n",
      " [1. 0. 0. 0.]\n",
      " [0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]]\n",
      "\n",
      "\n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [1. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    " \n",
    "a=np.eye(3)\n",
    "print(a)\n",
    "print(\"\\n\")\n",
    " \n",
    "a=np.eye(4,k=1)\n",
    "print(a)\n",
    "print(\"\\n\")\n",
    "\n",
    "a=np.eye(4,k=-1)\n",
    "print(a)\n",
    "print(\"\\n\")\n",
    "\n",
    "a=np.eye(4,k=-3)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 快速创建数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1.]\n",
      " [1. 1.]]\n",
      "**********\n",
      "[[1. 1. 1.]\n",
      " [1. 1. 1.]]\n",
      "**********\n",
      "[[1. 1.]\n",
      " [1. 1.]\n",
      " [1. 1.]]\n",
      "**********\n",
      "[[1. 1.]\n",
      " [1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "# 快速创建二维数组\n",
    "a = np.ones([2,2])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([2,3])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([3,2])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([2,2])\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1. 1.]\n",
      "  [1. 1.]]\n",
      "\n",
      " [[1. 1.]\n",
      "  [1. 1.]]]\n",
      "**********\n",
      "[[[1. 1. 1.]\n",
      "  [1. 1. 1.]]\n",
      "\n",
      " [[1. 1. 1.]\n",
      "  [1. 1. 1.]]]\n",
      "**********\n",
      "[[[1. 1.]\n",
      "  [1. 1.]\n",
      "  [1. 1.]]\n",
      "\n",
      " [[1. 1.]\n",
      "  [1. 1.]\n",
      "  [1. 1.]]]\n",
      "**********\n",
      "[[[1. 1.]\n",
      "  [1. 1.]]\n",
      "\n",
      " [[1. 1.]\n",
      "  [1. 1.]]\n",
      "\n",
      " [[1. 1.]\n",
      "  [1. 1.]]]\n"
     ]
    }
   ],
   "source": [
    "# 快速创建三维数组\n",
    "a = np.ones([2,2,2])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([2,2,3])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([2,3,2])\n",
    "print(a)\n",
    "print('*'*10)\n",
    "\n",
    "a = np.ones([3,2,2])\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从上面的代码可以看出，三维情况创建时后面2个参数可以看做是创建二维数组，第1个参数看做创建的二维数组的个数，所以创建时输入的参数为2,3,2时，就相当于创建了2个3行2列的二维数组。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 练习题：创建一个五维数组的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[[[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]]\n",
      "\n",
      "\n",
      "  [[[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]]]\n",
      "\n",
      "\n",
      "\n",
      " [[[[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]]\n",
      "\n",
      "\n",
      "  [[[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]\n",
      "\n",
      "   [[1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]\n",
      "    [1. 1. 1. 1. 1.]]]]]\n",
      "5\n",
      "(2, 2, 3, 3, 5)\n",
      "[[1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "c= np.ones([2,2,3,3,5]) \n",
    "print(c)\n",
    "print(c.ndim) \n",
    "print(c.shape)\n",
    "print(c[0,1,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其他数组相关方法，请查看[文档](https://numpy.org/doc/1.18/user/basics.creation.html#arrays-creation)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 数据类型\n",
    "每个Numpy数组都是数据类型相同的元素组成的网格。Numpy提供了很多的数据类型用于创建数组。当你创建数组的时候，Numpy会尝试猜测数组的数据类型，你也可以通过参数直接指定数据类型，例子如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "int64\n",
      "float64\n",
      "int64\n",
      "[[1. 1.]\n",
      " [1. 1.]]\n",
      "[[  1. 100.]\n",
      " [  1.   1.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2])  # Let numpy choose the datatype\n",
    "print(x.dtype)         # Prints \"int64\"\n",
    "\n",
    "x = np.array([1.0, 2.0])  # Let numpy choose the datatype\n",
    "print(x.dtype)             # Prints \"float64\"\n",
    "\n",
    "x = np.array([1, 2], dtype=np.int64)  # Force a particular datatype\n",
    "print(x.dtype)                        # Prints \"int64\"\n",
    "\n",
    "# 如果你想将数组的内容改成字符串就会报错。\n",
    "a = np.ones([2,2])\n",
    "print(a)\n",
    "# a[0,1]='一百'\n",
    "a[0,1]=100\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "更多细节查看[文档](https://numpy.org/doc/1.18/reference/arrays.dtypes.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1.]\n",
      " [1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "# 指定数据类型\n",
    "a = np.ones([2,2],dtype=float)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 1]\n",
      " [1 1]]\n"
     ]
    }
   ],
   "source": [
    "a = np.ones([2,2],dtype=int)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[False False]\n",
      " [False False]]\n"
     ]
    }
   ],
   "source": [
    "a = np.zeros([2,2],dtype=bool)\n",
    "# a = np.ones([2,2],dtype=bool)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 访问数组\n",
    "Numpy提供了多种访问数组的方法。\n",
    "\n",
    "## 切片\n",
    "和Python列表类似，numpy数组可以使用切片语法。因为数组可以是多维的，所以你必须为每个维度指定好切片。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]]\n",
      "[[2 3]\n",
      " [6 7]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# Create the following rank 2 array with shape (3, 4)\n",
    "# [[ 1  2  3  4]\n",
    "#  [ 5  6  7  8]\n",
    "#  [ 9 10 11 12]]\n",
    "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
    "print(a)\n",
    "\n",
    "# Use slicing to pull out the subarray consisting of the first 2 rows\n",
    "# and columns 1 and 2; b is the following array of shape (2, 2):\n",
    "# [[2 3]\n",
    "#  [6 7]]\n",
    "b = a[:2, 1:3] # 注意左闭右开，或者又叫左包又不包，从0开始\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "[[77  3]\n",
      " [ 6  7]]\n",
      "[[ 1 77  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]]\n"
     ]
    }
   ],
   "source": [
    "# A 是 B 的部分，修改 B 之后，A 也会变。\n",
    "# A slice of an array is a view into the same data, so modifying it\n",
    "# will modify the original array.（深拷贝和浅拷贝？）\n",
    "print(a[0, 1])   # Prints \"2\"\n",
    "b[0, 0] = 77    # b[0, 0] is the same piece of data as a[0, 1]\n",
    "print(b)   # Prints \"77\"\n",
    "print(a)   # Prints \"77\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3 4]\n",
      " [4 3 2 1]\n",
      " [1 2 3 4]]\n",
      "[[8888    2    3]]\n"
     ]
    }
   ],
   "source": [
    "# 这种方式就不会影响，选出元素重新生成\n",
    "import numpy as np\n",
    "a = np.array([[1,2,3,4],[4,3,2,1],[1,2,3,4]])\n",
    "# interger indexing\n",
    "b = np.array(a[0:1,:3])\n",
    "b[0,0]=8888\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2 3 1]\n",
      "(3,)\n"
     ]
    }
   ],
   "source": [
    "# 另一种indexing取值方法\n",
    "c = a[[0,2,1],[1,2,3]]\n",
    "\n",
    "print(c)\n",
    "print(c.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 3 3]\n"
     ]
    }
   ],
   "source": [
    "# 用数组定位位置取数\n",
    "d = np.array([0,1,2])\n",
    "e = a[np.arange(3),d]\n",
    "print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[100   2   3   4]\n",
      " [  4 100   2   1]\n",
      " [  1   2 100   4]]\n"
     ]
    }
   ],
   "source": [
    "# 定位之后赋值\n",
    "a[np.arange(3),d] = 100\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 拓展"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "[0, 2, 3, 4]\n",
      "     0\n",
      "0    1\n",
      "1  999\n",
      "2    3\n",
      "3    4\n",
      "     0\n",
      "0    1\n",
      "1  999\n",
      "2    3\n",
      "3    4\n"
     ]
    }
   ],
   "source": [
    "# 列表：不修改原始的\n",
    "import pandas as pd\n",
    "a = [1,2,3,4]\n",
    "b = a[:]\n",
    "b[0] = 0\n",
    "print(a)\n",
    "print(b)\n",
    "\n",
    "\n",
    "# DataFrame：连同原始的一起修改\n",
    "df_a = pd.DataFrame(a)\n",
    "df_b = df_a[:]\n",
    "df_b.iloc[1,0] = 999\n",
    "print(df_a)\n",
    "print(df_b)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 习题"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[[ 0  1  2]\n",
      "   [ 3  4  5]]\n",
      "\n",
      "  [[ 6  7  8]\n",
      "   [ 9 10 11]]\n",
      "\n",
      "  [[12 13 14]\n",
      "   [15 16 17]]]\n",
      "\n",
      "\n",
      " [[[18 19 20]\n",
      "   [21 22 23]]\n",
      "\n",
      "  [[24 25 26]\n",
      "   [27 28 29]]\n",
      "\n",
      "  [[30 31 32]\n",
      "   [33 34 35]]]]\n"
     ]
    }
   ],
   "source": [
    "m = np.arange(36).reshape([2,3,2,3]) # 变维函数\n",
    "print(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "结果1\n",
      "[[[18 19 20]\n",
      "  [21 22 23]]\n",
      "\n",
      " [[24 25 26]\n",
      "  [27 28 29]]\n",
      "\n",
      " [[30 31 32]\n",
      "  [33 34 35]]]\n",
      "结果2\n",
      "[[[ 6  7  8]\n",
      "  [ 9 10 11]]\n",
      "\n",
      " [[24 25 26]\n",
      "  [27 28 29]]]\n",
      "结果3\n",
      "[[[ 3  4  5]\n",
      "  [ 9 10 11]\n",
      "  [15 16 17]]\n",
      "\n",
      " [[21 22 23]\n",
      "  [27 28 29]\n",
      "  [33 34 35]]]\n",
      "结果4\n",
      "[[[ 1  4]\n",
      "  [ 7 10]\n",
      "  [13 16]]\n",
      "\n",
      " [[19 22]\n",
      "  [25 28]\n",
      "  [31 34]]]\n"
     ]
    }
   ],
   "source": [
    "print('结果1')\n",
    "print(m[1,:,:,:])\n",
    "print('结果2')\n",
    "print(m[:,1,:,:])\n",
    "print('结果3')\n",
    "print(m[:,:,1,:])\n",
    "print('结果4')\n",
    "print(m[:,:,:,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 习题解读\n",
    "前面`print(m)`很好理解~\n",
    "\n",
    "然后print m[1,：,：,：]，：代表默认值（就是一开始你输入时指定的值），这句代码相当于输出2个包中的第1个包（从0开始计数），这个包里面有3个小包，小包里面是2*3的二维数组，所以结果就是上面的~\n",
    "\n",
    "然后print m[：,1,：,：]，相当于输出2个大包，每个大包输出第1个小包，小包里面是2*3的二维数组\n",
    "\n",
    "然后print m[：,：,1,：]，相当于输出2个大包，每个大包输出3个小包，小包里面是二维数组的第1行\n",
    "\n",
    "然后print m[：,：,：,1]，相当于输出2个大包，每个大包输出3个小包，小包里面是1*2的一维数组\n",
    "\n",
    "其他结果可以自己去试试~\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 整型数组访问\n",
    "当我们使用切片语法访问数组时，得到的总是原数组的一个子集。整型数组访问允许我们利用其它数组的数据构建一个新的数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "[1 4 5]\n",
      "[1 4 5]\n",
      "[2 2]\n",
      "[2 2]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a = np.array([[1,2], [3, 4], [5, 6]])\n",
    "print(a)\n",
    "\n",
    "# An example of integer array indexing.\n",
    "# The returned array will have shape (3,) and \n",
    "print(a[[0, 1, 2], [0, 1, 0]])  # Prints \"[1 4 5]\"\n",
    "\n",
    "# The above example of integer array indexing is equivalent to this:\n",
    "print(np.array([a[0, 0], a[1, 1], a[2, 0]]))  # Prints \"[1 4 5]\"\n",
    "\n",
    "# When using integer array indexing, you can reuse the same\n",
    "# element from the source array:\n",
    "print(a[[0, 0], [1, 1]])  # Prints \"[2 2]\"\n",
    "\n",
    "# Equivalent to the previous integer array indexing example\n",
    "print(np.array([a[0, 1], a[0, 1]]))  # Prints \"[2 2]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 布尔型数组访问\n",
    "布尔型数组访问可以让你选择数组中任意元素。通常，这种访问方式用于选取数组中满足某些条件的元素，举例如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "[[False False]\n",
      " [ True  True]\n",
      " [ True  True]]\n",
      "[3 4 5 6]\n",
      "[3 4 5 6]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a = np.array([[1,2], [3, 4], [5, 6]])\n",
    "print(a)\n",
    "\n",
    "bool_idx = (a > 2)  # Find the elements of a that are bigger than 2;\n",
    "                    # this returns a numpy array of Booleans of the same\n",
    "                    # shape as a, where each slot of bool_idx tells\n",
    "                    # whether that element of a is > 2.\n",
    "\n",
    "print(bool_idx)      # Prints \"[[False False]\n",
    "                    #          [ True  True]\n",
    "                    #          [ True  True]]\"\n",
    "\n",
    "# We use boolean array indexing to construct a rank 1 array\n",
    "# consisting of the elements of a corresponding to the True values\n",
    "# of bool_idx\n",
    "print(a[bool_idx])  # Prints \"[3 4 5 6]\"\n",
    "\n",
    "# We can do all of the above in a single concise statement:\n",
    "print(a[a > 2])     # Prints \"[3 4 5 6]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为了教程的简介，有很多数组访问的细节我们没有详细说明，可以查看[文档](https://numpy.org/doc/1.18/reference/arrays.indexing.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://pptwinpics.oss-cn-beijing.aliyuncs.com/CDA%E8%AE%B2%E5%B8%88%E6%B0%B4%E5%8D%B0_20200314161940.png)\n",
    "# 数组计算\n",
    "基本数学计算函数会对数组中元素逐个进行计算，既可以利用操作符重载，也可以使用函数方式：\n",
    "\n",
    "## 加减乘除，开平方根"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  2.]\n",
      " [ 3. 49.]]\n",
      "[[5. 6.]\n",
      " [7. 8.]]\n",
      "[[ 6.  8.]\n",
      " [10. 57.]]\n",
      "[[ 6.  8.]\n",
      " [10. 57.]]\n",
      "[[-4. -4.]\n",
      " [-4. 41.]]\n",
      "[[-4. -4.]\n",
      " [-4. 41.]]\n",
      "[[  5.  12.]\n",
      " [ 21. 392.]]\n",
      "[[  5.  12.]\n",
      " [ 21. 392.]]\n",
      "[[0.2        0.33333333]\n",
      " [0.42857143 6.125     ]]\n",
      "[[0.2        0.33333333]\n",
      " [0.42857143 6.125     ]]\n",
      "[[1.         1.41421356]\n",
      " [1.73205081 7.        ]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([[1,2],[3,49]], dtype=np.float64)\n",
    "y = np.array([[5,6],[7,8]], dtype=np.float64)\n",
    "print(x)\n",
    "print(y)\n",
    "\n",
    "# Elementwise sum; both produce the array\n",
    "# [[ 6.0  8.0]\n",
    "#  [10.0 12.0]]\n",
    "print(x + y)\n",
    "print(np.add(x, y))\n",
    "\n",
    "# Elementwise difference; both produce the array\n",
    "# [[-4.0 -4.0]\n",
    "#  [-4.0 -4.0]]\n",
    "print(x - y)\n",
    "print(np.subtract(x, y))\n",
    "\n",
    "# Elementwise product; both produce the array\n",
    "# [[ 5.0 12.0]\n",
    "#  [21.0 32.0]]\n",
    "print(x * y)\n",
    "print(np.multiply(x, y))\n",
    "\n",
    "# Elementwise division; both produce the array\n",
    "# [[ 0.2         0.33333333]\n",
    "#  [ 0.42857143  0.5       ]]\n",
    "print(x / y)\n",
    "print(np.divide(x, y))\n",
    "\n",
    "# Elementwise square root; produces the array\n",
    "# [[ 1.          1.41421356]\n",
    "#  [ 1.73205081  2.        ]]\n",
    "print(np.sqrt(x)) # 开平方根"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "和MATLAB不同，*是元素逐个相乘，而不是矩阵乘法。在Numpy中使用dot来进行矩阵乘法：\n",
    "\n",
    "## 点乘dot()\n",
    "\n",
    "![](https://pptwinpics.oss-cn-beijing.aliyuncs.com/dot-juzhen-diancheng_20200321133117.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "[[5 6]\n",
      " [7 8]]\n",
      "[[19 22]\n",
      " [43 50]]\n",
      "[3 0]\n",
      "[0 4]\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([[1,2],[3,4]])\n",
    "y = np.array([[5,6],[7,8]])\n",
    "print(x)\n",
    "print(y)\n",
    "\n",
    "v = np.array([9,10])\n",
    "w = np.array([11, 12])\n",
    "\n",
    "# Inner product of vectors; both produce 219\n",
    "# print(v.dot(w))\n",
    "# print(np.dot(v, w))\n",
    "\n",
    "# Matrix / vector product; both produce the rank 1 array [29 67]\n",
    "# print(x.dot(v))\n",
    "# print(np.dot(x, v))\n",
    "\n",
    "# Matrix / matrix product; both produce the rank 2 array\n",
    "# [[19 22]\n",
    "#  [43 50]]\n",
    "print(x.dot(y)) # 5+14=19，1*6\n",
    "# print(np.dot(x, y))\n",
    "\n",
    "i = np.array([3,0])\n",
    "print(i)\n",
    "j = np.array([0,4])\n",
    "print(j)\n",
    "print(i.dot(j))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 9 12 15]\n",
      " [24 33 42]\n",
      " [39 54 69]]\n"
     ]
    }
   ],
   "source": [
    "# 3X2 矩阵 乘以 2X3 矩阵,中间两个数一样，才能消除\n",
    "a = np.array([[1,2],\n",
    "              [4,5],\n",
    "              [7,8]])\n",
    "\n",
    "b = np.array([[1,2,3],\n",
    "              [4,5,6]])\n",
    "\n",
    "print(a.dot(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "shapes (3,2) and (3,3) not aligned: 2 (dim 1) != 3 (dim 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-37-317d90637f9f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      8\u001b[0m               [7,8,9]])\n\u001b[1;32m      9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: shapes (3,2) and (3,3) not aligned: 2 (dim 1) != 3 (dim 0)"
     ]
    }
   ],
   "source": [
    "# 3X2 矩阵 乘以 3X3 矩阵\n",
    "a = np.array([[1,2],\n",
    "              [4,5],\n",
    "              [7,8]])\n",
    "\n",
    "b = np.array([[1,2,3],\n",
    "              [4,5,6],\n",
    "              [7,8,9]])\n",
    "\n",
    "print(a.dot(b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Numpy提供了很多计算数组的函数，其中最常用的一个是sum："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "10\n",
      "[4 6]\n",
      "[3 7]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([[1,2],[3,4]])\n",
    "print(x)\n",
    "\n",
    "print(np.sum(x))  # Compute sum of all elements; prints \"10\"\n",
    "print(np.sum(x, axis=0))  # Compute sum of each column; prints \"[4 6]\"\n",
    "print(np.sum(x, axis=1))  # Compute sum of each row; prints \"[3 7]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "想要了解更多函数，可以查看[文档](https://numpy.org/doc/1.18/reference/routines.math.html)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 合并数组\n",
    "## np.vstack() 上下合并"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 1 1]\n",
      " [2 2 2]]\n",
      "(3,) (2, 3)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "A = np.array([1,1,1])\n",
    "B = np.array([2,2,2])\n",
    "         \n",
    "print(np.vstack((A,B)))    # vertical stack \n",
    "\"\"\"\n",
    "[[1,1,1]\n",
    " [2,2,2]]\n",
    "\"\"\"\n",
    " \n",
    "C = np.vstack((A,B))      \n",
    "print(A.shape,C.shape)\n",
    " \n",
    "# (3,) (2,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## np.hstack() 左右合并"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 1 1 2 2 2]\n",
      "(3,) (6,)\n"
     ]
    }
   ],
   "source": [
    "D = np.hstack((A,B))       # horizontal stack\n",
    " \n",
    "print(D)\n",
    "# [1,1,1,2,2,2]\n",
    " \n",
    "print(A.shape,D.shape)\n",
    "# (3,) (6,)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 分割数组\n",
    "## 纵向分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "[array([[0, 1],\n",
      "       [4, 5],\n",
      "       [8, 9]]), array([[ 2,  3],\n",
      "       [ 6,  7],\n",
      "       [10, 11]])]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n[array([[0, 1],\\n        [4, 5],\\n        [8, 9]]), array([[ 2,  3],\\n        [ 6,  7],\\n        [10, 11]])]\\n'"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "A = np.arange(12).reshape((3, 4))\n",
    "print(A)\n",
    "\"\"\"\n",
    "array([[ 0,  1,  2,  3],\n",
    "    [ 4,  5,  6,  7],\n",
    "    [ 8,  9, 10, 11]])\n",
    "\"\"\"\n",
    " \n",
    "print(np.split(A, 2, axis=1))\n",
    "\"\"\"\n",
    "[array([[0, 1],\n",
    "        [4, 5],\n",
    "        [8, 9]]), array([[ 2,  3],\n",
    "        [ 6,  7],\n",
    "        [10, 11]])]\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 横向分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]\n"
     ]
    }
   ],
   "source": [
    "print(np.split(A, 3, axis=0))\n",
    "# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 等量分割\n",
    "在Numpy里还有`np.vsplit()`与`np.hsplit()`方式可用。vertical可理解为沿着垂直方向横向切割行row的操作，horizontal可理解为沿着水平方向纵向切割列的操作。注意：也必须为等量分割。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]\n",
      "[array([[0],\n",
      "       [4],\n",
      "       [8]]), array([[1],\n",
      "       [5],\n",
      "       [9]]), array([[ 2],\n",
      "       [ 6],\n",
      "       [10]]), array([[ 3],\n",
      "       [ 7],\n",
      "       [11]])]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n[array([[0, 1],\\n       [4, 5],\\n       [8, 9]]), array([[ 2,  3],\\n        [ 6,  7],\\n        [10, 11]])]\\n'"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(np.vsplit(A, (3))) #等于 print(np.split(A, 3, axis=0))\n",
    " \n",
    "# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]\n",
    " \n",
    " \n",
    "print(np.hsplit(A, 4)) #等于 print(np.split(A, 2, axis=1))\n",
    "\n",
    "\"\"\"\n",
    "[array([[0, 1],\n",
    "       [4, 5],\n",
    "       [8, 9]]), array([[ 2,  3],\n",
    "        [ 6,  7],\n",
    "        [10, 11]])]\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 不等量分割\n",
    "上述均为等量分割，若为不等量时，如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[0, 1],\n",
      "       [4, 5],\n",
      "       [8, 9]]), array([[ 2],\n",
      "       [ 6],\n",
      "       [10]]), array([[ 3],\n",
      "       [ 7],\n",
      "       [11]])]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n[array([[0, 1],\\n        [4, 5],\\n        [8, 9]]), array([[ 2],\\n        [ 6],\\n        [10]]), array([[ 3],\\n        [ 7],\\n        [11]])]\\n'"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(np.array_split(A, 3, axis=1))\n",
    "\"\"\"\n",
    "[array([[0, 1],\n",
    "        [4, 5],\n",
    "        [8, 9]]), array([[ 2],\n",
    "        [ 6],\n",
    "        [10]]), array([[ 3],\n",
    "        [ 7],\n",
    "        [11]])]\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 转置"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "除了计算，我们还常常改变数组或者操作其中的元素。其中将矩阵转置是常用的一个，在Numpy中，使用T来转置矩阵："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "[[1 3]\n",
      " [2 4]]\n",
      "[1 2 3]\n",
      "[1 2 3]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([[1,2], [3,4]])\n",
    "print(x)    # Prints \"[[1 2]\n",
    "           #          [3 4]]\"\n",
    "print(x.T)  # Prints \"[[1 3]\n",
    "           #          [2 4]]\"\n",
    "\n",
    "# Note that taking the transpose of a rank 1 array does nothing:\n",
    "v = np.array([1,2,3])\n",
    "print(v)    # Prints \"[1 2 3]\"\n",
    "print(v.T)  # Prints \"[1 2 3]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 广播Broadcasting\n",
    "广播是一种强有力的机制，它让Numpy可以让不同大小的矩阵在一起进行数学计算。我们常常会有一个小的矩阵和一个大的矩阵，然后我们会需要用小的矩阵对大的矩阵做一些计算。\n",
    "\n",
    "举个例子，如果我们想要把一个向量加到矩阵的每一行，我们可以这样做："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 2  2  4]\n",
      " [ 5  5  7]\n",
      " [ 8  8 10]\n",
      " [11 11 13]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# We will add the vector v to each row of the matrix x,\n",
    "# storing the result in the matrix y\n",
    "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
    "v = np.array([1, 0, 1])\n",
    "y = np.empty_like(x)   # Create an empty matrix with the same shape as x\n",
    "\n",
    "# Add the vector v to each row of the matrix x with an explicit loop\n",
    "for i in range(4):\n",
    "    y[i, :] = x[i, :] + v\n",
    "\n",
    "# Now y is the following\n",
    "# [[ 2  2  4]\n",
    "#  [ 5  5  7]\n",
    "#  [ 8  8 10]\n",
    "#  [11 11 13]]\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这样是行得通的，但是当x矩阵非常大，利用循环来计算就会变得很慢很慢。我们可以换一种思路："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 0 1]\n",
      " [1 0 1]\n",
      " [1 0 1]\n",
      " [1 0 1]]\n",
      "[[ 2  2  4]\n",
      " [ 5  5  7]\n",
      " [ 8  8 10]\n",
      " [11 11 13]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# We will add the vector v to each row of the matrix x,\n",
    "# storing the result in the matrix y\n",
    "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
    "v = np.array([1, 0, 1])\n",
    "vv = np.tile(v, (4, 1))  # Stack 4 copies of v on top of each other\n",
    "print(vv)                # Prints \"[[1 0 1]\n",
    "                         #          [1 0 1]\n",
    "                         #          [1 0 1]\n",
    "                         #          [1 0 1]]\"\n",
    "y = x + vv  # Add x and vv elementwise\n",
    "print(y)  # Prints \"[[ 2  2  4\n",
    "         #          [ 5  5  7]\n",
    "         #          [ 8  8 10]\n",
    "         #          [11 11 13]]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Numpy广播机制可以让我们不用创建vv，就能直接运算，看看下面例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 2  2  4]\n",
      " [ 5  5  7]\n",
      " [ 8  8 10]\n",
      " [11 11 13]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# We will add the vector v to each row of the matrix x,\n",
    "# storing the result in the matrix y\n",
    "x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
    "v = np.array([1, 0, 1])\n",
    "y = x + v  # Add v to each row of x using broadcasting\n",
    "print(y)  # Prints \"[[ 2  2  4]\n",
    "         #          [ 5  5  7]\n",
    "         #          [ 8  8 10]\n",
    "         #          [11 11 13]]\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 图片解读\n",
    "![](https://pptwinpics.oss-cn-beijing.aliyuncs.com/numpy-guangbo_20200213111309.png)\n",
    "\n",
    "## 注意\n",
    "\n",
    "对两个数组使用广播机制要遵守下列规则：\n",
    "\n",
    "- 如果数组的秩不同，使用1来将秩较小的数组进行扩展，直到两个数组的尺寸的长度都一样。\n",
    "- 如果两个数组在某个维度上的长度是一样的，或者其中一个数组在该维度上长度为1，那么我们就说这两个数组在该维度上是相容的。\n",
    "- 如果两个数组在所有维度上都是相容的，他们就能使用广播。\n",
    "- 如果两个输入数组的尺寸不同，那么注意其中较大的那个尺寸。因为广播之后，两个数组的尺寸将和那个较大的尺寸一样。\n",
    "- 在任何一个维度上，如果一个数组的长度为1，另一个数组长度大于1，那么在该维度上，就好像是对第一个数组进行了复制。\n",
    "\n",
    "如果上述解释看不明白，可以读一读[文档](https://numpy.org/doc/1.18/user/basics.broadcasting.html)和这个[解释](http://scipy.github.io/old-wiki/pages/EricsBroadcastingDoc)。强烈推荐阅读文档中的例子。\n",
    "\n",
    "支持广播机制的函数是全局函数。哪些是全局函数可以在文档中查找。\n",
    "\n",
    "下面是一些广播机制的使用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 4  5]\n",
      " [ 8 10]\n",
      " [12 15]]\n",
      "[[2 4 6]\n",
      " [5 7 9]]\n",
      "[[ 5  6  7]\n",
      " [ 9 10 11]]\n",
      "[[ 5  6  7]\n",
      " [ 9 10 11]]\n",
      "[[ 2  4  6]\n",
      " [ 8 10 12]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# Compute outer product of vectors\n",
    "v = np.array([1,2,3])  # v has shape (3,)\n",
    "w = np.array([4,5])    # w has shape (2,)\n",
    "# To compute an outer product, we first reshape v to be a column\n",
    "# vector of shape (3, 1); we can then broadcast it against w to yield\n",
    "# an output of shape (3, 2), which is the outer product of v and w:\n",
    "# [[ 4  5]\n",
    "#  [ 8 10]\n",
    "#  [12 15]]\n",
    "print(np.reshape(v, (3, 1)) * w)\n",
    "\n",
    "# Add a vector to each row of a matrix\n",
    "x = np.array([[1,2,3], [4,5,6]])\n",
    "# x has shape (2, 3) and v has shape (3,) so they broadcast to (2, 3),\n",
    "# giving the following matrix:\n",
    "# [[2 4 6]\n",
    "#  [5 7 9]]\n",
    "print(x + v)\n",
    "\n",
    "# Add a vector to each column of a matrix\n",
    "# x has shape (2, 3) and w has shape (2,).\n",
    "# If we transpose x then it has shape (3, 2) and can be broadcast\n",
    "# against w to yield a result of shape (3, 2); transposing this result\n",
    "# yields the final result of shape (2, 3) which is the matrix x with\n",
    "# the vector w added to each column. Gives the following matrix:\n",
    "# [[ 5  6  7]\n",
    "#  [ 9 10 11]]\n",
    "print((x.T + w).T)\n",
    "\n",
    "# Another solution is to reshape w to be a row vector of shape (2, 1);\n",
    "# we can then broadcast it directly against x to produce the same\n",
    "# output.\n",
    "print(x + np.reshape(w, (2, 1)))\n",
    "\n",
    "# Multiply a matrix by a constant:\n",
    "# x has shape (2, 3). Numpy treats scalars as arrays of shape ();\n",
    "# these can be broadcast together to shape (2, 3), producing the\n",
    "# following array:\n",
    "# [[ 2  4  6]\n",
    "#  [ 8 10 12]]\n",
    "print(x * 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "广播机制能够让你的代码更简洁更迅速，能够用的时候请尽量使用！\n",
    "\n",
    "# Numpy文档\n",
    "这篇教程涉及了你需要了解的numpy中的一些重要内容，但是numpy远不止如此。可以查阅[numpy文献](https://numpy.org/doc/1.18/reference/)来学习更多。\n",
    "\n",
    "![](https://pptwinpics.oss-cn-beijing.aliyuncs.com/CDA%E8%AE%B2%E5%B8%88%E6%B0%B4%E5%8D%B0_20200314161940.png)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "269.594px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
